package scau.zxck.utils;

import javafx.scene.control.CheckBoxTreeItem;
import javafx.scene.control.TreeItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import scau.zxck.entity.Connection;
import scau.zxck.entity.TableInfo;
import scau.zxck.view.Main;
import scau.zxck.view.node.MyCheckBoxTreeItem;
import scau.zxck.view.node.MyTreeItem;
import scau.zxck.view.stage.AlertStage;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ViewUtil {

    // 配置文件路径
    public static String configFilePath = PathUtil.getAbsolutePath(PropUtil.getBasicProp("Config_File_Path"));
    /**
     * 初始化连接树界面
     * @throws Exception
     */
    public static void initConnTreeInterface() throws Exception {
        System.out.println(configFilePath);
        File configFile = new File(configFilePath);
        if (configFile.exists())
            Main.connectionList = getConnsByConfigFile();
        else {
            try {
                configFile.createNewFile();
                writeInfoToConfigFile();
            } catch (IOException e) {
                new AlertStage("Error", "Failed to create config file").show();
                e.printStackTrace();
            }
        }
    }

    /**
     * 初始化表名树界面
     */
    public static void initTableTreeInterface() {
        File configFile = new File(configFilePath);
        if (configFile.exists())
            Main.defaultOutDir = getDefaultOutDirByConfigFile();
        else {
            try {
                configFile.createNewFile();
                writeInfoToConfigFile();
            } catch (IOException e) {
                new AlertStage("Error", "Failed to create config file").show();
                e.printStackTrace();
            }
        }
    }

    /**
     * 通过配置文件读取连接到connectionList中
     * @return
     */
    public static List<Connection> getConnsByConfigFile() {
        File configFile = new File(configFilePath);
        Document configDoc = null;
        try {
            configDoc = new SAXReader().read(configFile);
        } catch (DocumentException e) {
            new AlertStage("Error", "Failed to read config file").show();
            e.printStackTrace();
        }
        Element rootEle = configDoc.getRootElement();
        List<Element> connEleList = rootEle.element("connections").elements("connection");
        List<Connection> connListFromConfig = new ArrayList<Connection>();
        for(Element connEle : connEleList){
            String connName = connEle.element("connName").getText();
            String host = connEle.element("host").getText();
            String userName = connEle.element("userName").getText();
            String password = connEle.element("password").getText();
            String port = connEle.element("port").getText();
            Connection conn = new Connection(connName, host, userName, password, port);
            connListFromConfig.add(conn);
        }
        return connListFromConfig;
    }

    /**
     * 通过配置文件读取默认输出路径到defaultOutDir中
     * @return
     */
    public static String getDefaultOutDirByConfigFile() {
        File configFile = new File(configFilePath);
        Document configDoc = null;
        try {
            configDoc = new SAXReader().read(configFile);
        } catch (DocumentException e) {
            new AlertStage("Error", "Failed to read config file").show();
            e.printStackTrace();
        }
        Element rootEle = configDoc.getRootElement();
        Element outDirEle = rootEle.element("defaultOutDir");
        return outDirEle.getText();
    }

    /**
     * 将Main中的connectionList和defaultOutDir写入配置文件
     */
    public static void writeInfoToConfigFile() {
        Document doc = DocumentHelper.createDocument();
        doc.setXMLEncoding("utf-8");
        Element rootEle = doc.addElement("userConfig");
        // 保存连接
        Element connEle = rootEle.addElement("connections");
        for (Connection conn : Main.connectionList) {
            Element tempEle = connEle.addElement("connection");
            Element connNameEle = tempEle.addElement("connName");
            connNameEle.setText(conn.getConnName());
            Element hostEle = tempEle.addElement("host");
            hostEle.setText(conn.getHost());
            Element userNameEle = tempEle.addElement("userName");
            userNameEle.setText(conn.getUserName());
            Element passwordEle = tempEle.addElement("password");
            passwordEle.setText(conn.getPassword());
            Element portEle = tempEle.addElement("port");
            portEle.setText(conn.getPort());
        }
        // 保存默认输出路径
        Element outDirEle = rootEle.addElement("defaultOutDir");
        outDirEle.setText(Main.defaultOutDir);
        // 输出XML
        FileOutputStream fileOutputStream = null;
        XMLWriter xmlWriter = null;
        try {
            fileOutputStream = new FileOutputStream(configFilePath);
            xmlWriter = new XMLWriter(new OutputStreamWriter(fileOutputStream, "utf-8"));
            xmlWriter.write(doc);
            xmlWriter.close();
        } catch (FileNotFoundException e) {
            try {
                new File(configFilePath).createNewFile();
                writeInfoToConfigFile();
            } catch (IOException e1) {
                new AlertStage("Error", "Failed to create config file").show();
                e1.printStackTrace();
            }
        } catch (UnsupportedEncodingException e) {
            new AlertStage("Error", "Failed to write config file").show();
            e.printStackTrace();
        } catch (IOException e) {
            new AlertStage("Error", "Failed to write config file").show();
        }
    }

    /**
     * 根据connectionList创建连接树根节点
     * @return
     */
    public static TreeItem buildConnTreeRootItem() {
        MyTreeItem rootItem = new MyTreeItem("Connections");
        if(Main.connectionList.isEmpty()) {
            MyTreeItem emptyItem = new MyTreeItem("Empty", -2, -2);
            rootItem.getChildren().add(emptyItem);
        }
        else {
            for (int i=0;i<Main.connectionList.size();i++) {
                Connection conn = Main.connectionList.get(i);
                MyTreeItem connItem = new MyTreeItem(conn.getConnName(), i);
                if (conn.isConnected()) {
                    connItem.setGraphic(new ImageView(new Image("image/conn_connected.png")));
                    for (int j=0;j<conn.getDatabaseList().size();j++) {
                        MyTreeItem dbItem = new MyTreeItem(conn.getDatabaseList().get(j), i, j);
                        dbItem.setGraphic(new ImageView(new Image("image/database.png")));
                        connItem.getChildren().add(dbItem);
                    }
                    connItem.setExpanded(true);
                } else
                    connItem.setGraphic(new ImageView(new Image("image/conn_close.png")));
                rootItem.getChildren().add(connItem);
            }
        }
        rootItem.setExpanded(true);
        return rootItem;
    }

    /**
     * 根据tableList创建表名树根节点
     * @return
     */
    public static CheckBoxTreeItem buildTableTreeRootItem() {
        MyTreeItem selectedItem = Main.connTreeController.getSelectedItem();
        int connIndex = selectedItem.getConnIndex();
        int dbIndex = selectedItem.getDatabaseIndex();
        String databaseName = Main.connectionList.get(connIndex).getDatabaseList().get(dbIndex);

        MyCheckBoxTreeItem rootItem = new MyCheckBoxTreeItem(databaseName);
        rootItem.setGraphic(new ImageView(new Image("image/database.png")));
        if(Main.tableList.isEmpty()) {
            MyTreeItem emptyItem = new MyTreeItem("Empty", -2, -2);
            rootItem.getChildren().add(emptyItem);
        } else {
            for (int i=0;i<Main.tableList.size();i++) {
                TableInfo tableInfo = Main.tableList.get(i);
                MyCheckBoxTreeItem tableItem = new MyCheckBoxTreeItem(tableInfo.getTableName(), i);
                tableItem.setGraphic(new ImageView(new Image("image/table.png")));
                rootItem.getChildren().add(tableItem);
                tableItem.getChildren().add(new MyCheckBoxTreeItem("Entity", i, 0));
                tableItem.getChildren().add(new MyCheckBoxTreeItem("Dao", i, 1));
                tableItem.getChildren().add(new MyCheckBoxTreeItem("ServiceInterface", i, 2));
                tableItem.getChildren().add(new MyCheckBoxTreeItem("ServiceImpl", i, 3));
                tableItem.getChildren().add(new MyCheckBoxTreeItem("Action", i, 4));
                tableItem.getChildren().add(new MyCheckBoxTreeItem("Mapper", i, 5));
            }
        }
        rootItem.setExpanded(true);
        return rootItem;
    }
}